<?php

App::uses('CustomDataModel', 'Base.Model');
App::uses('ConfigurationKeys', 'ConfigurationKeys.Lib');
App::uses('AtomicOperation', 'Operations.Lib');
App::uses('FileOperations', 'Operations.Lib');

class SourceDocument extends CustomDataModel {

    public $displayField = 'name';
    public $hasMany = array(
        'RawFile',
        'SourceDocumentTag',
    );
    public $validate = array(
        'name' => array(
            'notempty' => array(
                'rule' => array('notempty'),
                'required' => true,
            ),
            'isUnique' => array(
                'rule' => array('isUnique'),
            ),
        )
    );

    public function __construct($id = false, $table = null, $ds = null) {
        parent::__construct($id, $table, $ds);
        $allDocumentsTagName = ConfigurationKeys::getKeyValueSql('all_documents_tag_name');
        $allDocumentsNonTaggedTagName = ConfigurationKeys::getKeyValueSql('all_documents_non_tagged_tag_name');
        $this->virtualFields['tagged'] = <<<EOT
((select count(*)
from {$this->SourceDocumentTag->tablePrefix}{$this->SourceDocumentTag->table} sdt
inner join {$this->SourceDocumentTag->Tag->tablePrefix}{$this->SourceDocumentTag->Tag->table} t 
    on t.id = sdt.tag_id
where 
sdt.source_document_id = {$this->alias}.id
and t.name not in ($allDocumentsTagName,$allDocumentsNonTaggedTagName)
    ) > 0)
EOT;
    }

    protected function customData() {
        $rawFilesDirectory = ConfigurationKeys::getRequiredKeyValue('raw_files_directory');
        if (!is_readable($rawFilesDirectory) || !is_dir($rawFilesDirectory)) {
            return array();
        }
        $rawFilesDirectoryIterator = new DirectoryIterator($rawFilesDirectory);

        $joinedRawFiles = array();

        while ($rawFilesDirectoryIterator->valid()) {
            if (!$rawFilesDirectoryIterator->isDot()) {
                $joinedRawFiles[$this->buildNameFromFileName($rawFilesDirectoryIterator->getFilename())] = true;
            }
            $rawFilesDirectoryIterator->next();
        }

        $sourceDocuments = array();

        foreach (array_keys($joinedRawFiles) as $sourceDocumentName) {
            $sourceDocuments[] = array(
                'name' => $sourceDocumentName,
            );
        }

        return $sourceDocuments;
    }

    public function buildNameFromFileName($fileName, $pattern = null) {
        if (!$pattern) {
            $pattern =  ConfigurationKeys::getRequiredKeyValue('joined_document_regex');
        }
        if (preg_match(
                       $pattern , $fileName, $matches
        )) {
            return empty($matches[1]) ? $fileName : $matches[1];
        } else {
            return $fileName;
        }
    }

    public function _renameFromFileName($oldName, $newName, $pattern = null) {
        if (!$pattern) {
            $pattern = ConfigurationKeys::getRequiredKeyValue('joined_document_regex');
        }
        if (preg_match(
                $pattern, $oldName, $matches, PREG_OFFSET_CAPTURE
        )) {
            $result = substr_replace(
                    $oldName
                    , $newName
                    , $matches[1][1]
                    , strlen($matches[1][0])
            );     
            return $result;
        } else {
            throw new Exception("No matched: " . print_r(compact('pattern', 'oldName'), true));
        }
    }

    protected function customSave($oldData, $newData) {
        if (empty($oldData)) {
            return false;
        }

        if (empty($newData['name'])) {
            return false;
        }


    }
    
    public function afterSave($created) {
        parent::afterSave($created);
        
        $rawFiles = $this->RawFile->findAllBySourceDocumentId($this->id);

        foreach ($rawFiles as $rawFile) {
            $rawFile['RawFile']['name'] = trim($this->_renameFromFileName($rawFile['RawFile']['name'], $this->data[$this->alias]['name']));
            Basics::saveModelOrThrowException($this->RawFile, $rawFile);
        }
    }

    protected function customDelete($row) {
        throw new Exception("Not supported");
    }

}

?>
